﻿using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using AMC.SubstitutionCache.Models;
using Orchard;
using Orchard.OutputCache.Services;

namespace AMC.SubstitutionCache.Services
{
    public interface ISubstitutionCacheControlStrategy : IDependency
    {
        bool ServeFromCache(ActionExecutingContext context);
        bool IsCacheable(ActionResult result, HttpResponseBase response);
    }

    public interface ICacheControlProvider
    {
        bool? ServeFromCache(ActionExecutingContext context);
        bool? IsCacheable(ActionResult result, HttpResponseBase response);
    }

    public abstract class CacheControlProvider : ICacheControlProvider
    {
        public virtual bool? ServeFromCache(ActionExecutingContext context)
        {
            return null;
        }

        public virtual bool? IsCacheable(ActionResult result, HttpResponseBase response)
        {
            return null;
        }
    }

    public class DefaultCacheControlStrategyProvider : CacheControlProvider
    {
        private readonly ICacheControlStrategy _cacheControlStrategy;

        public DefaultCacheControlStrategyProvider(ICacheControlStrategy cacheControlStrategy)
        {
            _cacheControlStrategy = cacheControlStrategy;
        }

        public override bool? ServeFromCache(ActionExecutingContext context)
        {
            var response = context.HttpContext.Response;

            //if the response location header has already been set, don't try to cache
            if (response.IsRequestBeingRedirected)
                return false;

            return null;
        }

        public override bool? IsCacheable(ActionResult result, HttpResponseBase response)
        {
            return _cacheControlStrategy.IsCacheable(result, response);
        }
    }

    public class DefaultSubstitutionCacheControlStrategy : ISubstitutionCacheControlStrategy
    {
        private readonly IEnumerable<ICacheControlProvider> _providers;

        public DefaultSubstitutionCacheControlStrategy(IEnumerable<ICacheControlProvider> providers)
        {
            _providers = providers;
        }

        public bool ServeFromCache(ActionExecutingContext context)
        {
            return _providers.All(provider => provider.ServeFromCache(context).GetValueOrDefault(true));
        }

        public bool IsCacheable(ActionResult result, HttpResponseBase response)
        {
            return _providers.All(provider => provider.IsCacheable(result, response).GetValueOrDefault(true));
        }
    }
}